#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/sem.h>
#include<string.h>

typedef struct _test{
	int a_val;
	int b_val;
	int a_flag;
	int b_flag;
	int game_no;
	int stage;
}test;

int pk[3][3] = {0,-1,1,1,0,-1,-1,1,0};

void sem_p();
void sem_v();
void set_sem();
void del_sem();
int sem_id;

union semun{
	int val;
	struct semid_ds *buf;
	unsigned short *arry;
};

int main(){
	int shmid;
	test* shm;
	
	shmid = shmget((key_t)1236,sizeof(test),0666|IPC_CREAT);	
	if(shmid == -1){
		printf("shmget failed\n");
		exit(EXIT_FAILURE);
	}
	printf("%d",shmid);

	shm = shmat(shmid,0,0);
	if (shm == (void*)-1){
		printf("shmat failed\n");
		exit(EXIT_FAILURE);
	}
	printf("\nMemory attached at %X\n",(int)shm);

	sem_id = semget((key_t)3000,1,0666|IPC_CREAT);
	set_sem();

	int no=0,debug=0,a,b;
	shm->a_flag=0;	shm->a_val = -2;
	shm->b_flag=0;	shm->b_val = -2;
	shm->game_no=1;
	shm->stage=0;
	while(1){
		sem_p();
		//printf("a:%d b:%d\n",shm->a_val,shm->b_val); sleep(1);
		if(shm->game_no==-1){
			sem_v();
			break;
		}
		if (shm->stage==0){
			if(no!=shm->game_no){
				no = shm->game_no;
				printf("-------------------\n");
				printf("game_no:%d\n",no);
			}
			if(shm->a_flag==1 && shm->b_flag==1) shm->stage=1;
		}
		else if(shm->stage==1){
			printf("a:%d\n",shm->a_val);
			printf("b:%d\n",shm->b_val);
			a = pk[shm->a_val][shm->b_val];
			b = pk[shm->b_val][shm->a_val];
			shm->a_val=a;
			shm->b_val=b;
			shm->a_flag=0;
			shm->b_flag=0;
			shm->stage=2;
		}
		else if(shm->stage==2){
			if(shm->a_flag==1 && shm->b_flag==1){
				shm->stage=0;
				shm->game_no++;
				shm->a_flag=0;
				shm->b_flag=0;
				printf("-------------------\n");
				if(shm->game_no > 100) shm->game_no=-1;
			}
		}
		sem_v();
	}

	shmdt(shm);

	int ret=0;
	ret = shmctl(shmid,IPC_RMID,NULL);
	if(ret<0){
		printf("shmctl error!\n");
	}

	del_sem();

	printf("finish");
}

void set_sem(){
	union semun sem_union;
	sem_union.val=1;
	semctl(sem_id,0,SETVAL,sem_union);
}

void del_sem(){
	union semun sem_union;
	semctl(sem_id,0,IPC_RMID,sem_union);
}

void sem_p(){
	struct sembuf sem_b;
	sem_b.sem_num = 0;
	sem_b.sem_op = -1;
	sem_b.sem_flg = SEM_UNDO;
	semop(sem_id,&sem_b,1);
}

void sem_v(){
	struct sembuf sem_b;
	sem_b.sem_num = 0;
	sem_b.sem_op = 1;
	sem_b.sem_flg = SEM_UNDO;
	semop(sem_id,&sem_b,1);
}
